#include <iostream>
#include <vector>
#include <queue>
#include <mutex>
#include <unistd.h>
#include <functional>
#include "Thread.hpp"
#include "Log.hpp"
using namespace std;
using ThreadModule::Thread;
int g_defaultnum = 3;
// 线程池本质是生产者和消费者模型，需要保证生产者和消费者的互斥和同步以及生产者之间、消费者之间的互斥
template <typename T>
class ThreadPool
{
private:
    void LockQueue()
    {
        pthread_mutex_lock(&_mutex);
    }
    void UnLockQueue()
    {
        pthread_mutex_unlock(&_mutex);
    }
    void ThreadSleep()
    {
        pthread_cond_wait(&_cond, &_mutex);
    }
    void ThreadWake()
    {
        pthread_cond_signal(&_cond);
    }
    void WakeAllThread()
    {
        pthread_cond_broadcast(&_cond);
    }
    // 每一个线程都会执行下面的代码
    void HandleTask(string name) // 类的成员方法，可以作为另一个类(Thread)的回调方法 需要将该成员方法与该类对象绑定传递给另一个类
    {
        /*从任务队列中读取任务并执行 */
        LOG(INFO, "%s is running", name.c_str());
        while (true) // 每个线程不退出，一直执行任务
        {

            // 1.获取任务
            // a.加锁 保证队列安全
            LockQueue();
            // b.队列为空&&线程池运行 -> 等待
            while (_task_queue.empty() && _isrunning) // 防止伪唤醒
            {
                _waitnum++;
                ThreadSleep();
                _waitnum--;
            }
            // 队列为空&&线程池暂停 ->退出
            if (_task_queue.empty() && !_isrunning)
            {
                UnLockQueue();
                // cout << name << "quit..." << endl;
                break;
            }
            // 队列不为空&&线程池运行 -> 执行任务
            // 队列不为空&&线程池暂停 -> 执行任务
            T t = _task_queue.front();
            _task_queue.pop();
            UnLockQueue();
            // 执行任务时，是线程独占的，在解锁之后执行任务,保证执行任务和获取任务是并发的
            LOG(INFO, "%s get a task", name.c_str());
            t(); // 需要重载() ，让它执行任务
        // LOG(INFO, "%s handle task done, result : %s", name.c_str(), t.ResultToString().c_str());
        }
    }
    // 初始化线程池
    void InitThreadPool()
    {
        for (int i = 0; i < _threadnum; i++)
        {
            string name = "thread-" + to_string(i + 1);
            function<void(string)> HandleTask_bind = bind(&ThreadPool<T>::HandleTask, this, placeholders::_1); // 将Print和this绑定
            _threads.emplace_back(HandleTask_bind, name);
            LOG(INFO, "%s init success", name.c_str());
        }
        _isrunning = true;
    }

    // 线程池开始执行任务
    void Start()
    {
        for (auto &t : _threads)
        {
            t.Start();
        }
        //_isrunning = true;
    }

    // 终止线程池
    void Stop()
    {
        LockQueue();
        _isrunning = false;
        UnLockQueue();
        WakeAllThread(); // 唤醒所有线程
    }

public:
    ThreadPool(int threadnum = g_defaultnum)
        : _threadnum(threadnum), _waitnum(0), _isrunning(false)
    {
        LOG(INFO, "thread pool create done");
        pthread_mutex_init(&_mutex, nullptr);
        pthread_cond_init(&_cond, nullptr);
    }
    ~ThreadPool()
    {
        LOG(INFO, "thread pool is destroy");
        pthread_mutex_destroy(&_mutex);
        pthread_cond_destroy(&_cond);
    }

    // 回收所有线程
    void Wait()
    {
        for (auto &t : _threads)
        {
            // cout << "name: " << t.name() << endl;
            LOG(INFO, "%s is quit...", t.name().c_str());
            t.Join();
        }
    }

    // 向线程池派发任务
    bool push(const T &t)
    {
        bool ret = false;
        LockQueue(); // 保护队列
        _task_queue.push(t);
        if (_waitnum > 0 && _isrunning) // 派发任务后将等待的线程苏醒
        {
            ThreadWake();
            ret = true;
        }
        UnLockQueue();
        return ret;
    }

    static ThreadPool<T> *GetInstance()
    {
        // 创建单例
        // 双重if减少锁的粒度
        if (_instance == nullptr)
        {
            LockGuard lockguard(_singleton_mutex);
            if (_instance == nullptr)
            {
                _instance = new ThreadPool<T>(g_defaultnum);
                _instance->InitThreadPool();
                _instance->Start();
                LOG(INFO, "创建线程池单例");
                return _instance;
            }
        }
        // 获取单例
        LOG(INFO, "获取线程池单例");
        return _instance;
    }

    static void DeleteInstance()
    {
        LOG(INFO, "删除线程池单例");
        delete _instance;
    }

private:
    int _threadnum;          // 线程个数
    vector<Thread> _threads; // 所有线程
    queue<T> _task_queue;    // 任务队列 线程从中取出任务

    pthread_mutex_t _mutex; // 任务队列的互斥锁
    pthread_cond_t _cond;   // 任务队列的条件变量

    int _waitnum;    // 没有执行任务的线程个数
    bool _isrunning; // 线程池运行状态

    // 懒汉实现单例
    static ThreadPool<T> *_instance;         // 声明在类中，类的成员函数可以访问
    static pthread_mutex_t _singleton_mutex; // 创建单例时加锁，
};

template <typename T>
ThreadPool<T> *ThreadPool<T>::_instance = nullptr;

template <typename T>
pthread_mutex_t ThreadPool<T>::_singleton_mutex = PTHREAD_MUTEX_INITIALIZER;
